package cn.edu.zzuli.nothinglink.service.impl;

import cn.edu.zzuli.nothinglink.entity.*;
import cn.edu.zzuli.nothinglink.mapper.*;
import cn.edu.zzuli.nothinglink.service.WorkPostponeService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author suzyyy
 * @since 2021-04-08
 */
@Service
public class WorkPostponeServiceImpl extends ServiceImpl<WorkPostponeMapper, WorkPostpone> implements WorkPostponeService {

    @Resource
    WorkMapper workMapper;

    @Resource
    CourseMapper courseMapper;

    @Resource
    StudentsMapper studentsMapper;

    @Autowired
    WorkPutPostponeRecordMapper workPutPostponeRecordMapper;

    @Resource
    WorkPostponeMapper workPostponeMapper;

    @Autowired
    ThreadPoolExecutor executor;

    @Override
    public R getWorkPostpone(boolean isStu, Integer id) {
        if (isStu) {
            //这里暂定学生查询的计划删除，换到workPutPostponeService中
            return R.success();
        }else {
            //是教师
            List<WorkPostpone> postpones = list(new LambdaQueryWrapper<WorkPostpone>().eq(WorkPostpone::getTeaId, id));

            if (postpones.size() == 0) return R.success().add("postpones", null);
            Set<Integer> workIds = postpones.stream()
                    .map(p -> p.getWorkId()).collect(Collectors.toSet());

            Map<Integer, Work> workMap = workMapper.selectBatchIds(workIds).stream().collect(Collectors.toMap(k -> k.getWorkId(), v -> v));
            postpones.stream().forEach(p -> {
                Work w = workMap.get(p.getWorkId());
                p.setCourseName(w.getCourseName());
                p.setWorkName(w.getWorkName());
            });

            return R.success().add("postpones", postpones);
        }
    }

    @Override
    public R getWorkPostponeCondition(Integer wpId) {
        //获取该作业绑定的课程，班级详细情况
        WorkPostpone workPostpone = this.getById(wpId);
        if (workPostpone == null) return R.error();
        //作业详情
        Work work = workMapper.selectById(workPostpone.getWorkId());
        AtomicReference<Integer> stuTotalCount = new AtomicReference<>(0);

        CompletableFuture<Map<Integer, Classes>> getClassesInfoTask = CompletableFuture.supplyAsync(() -> {
            String content = work.getContent();
            content = JSONObject.parseObject(content, JSONObject.class).getString("content");
            work.setContent(content);

            Course course = courseMapper.selectById(work.getCourseId());

            //获取班级详情
            Map<Integer, Classes> classesMap = courseMapper.getClassInTheCourses(course.getCourseId())
                    .stream().collect(Collectors.toMap(Classes::getClassId, v -> v));

            if (classesMap.size() != 0) {
                //获取班级中全部的人数
                List<Students> students = studentsMapper.selectList(
                        new LambdaQueryWrapper<Students>().in(Students::getBelongClassId, classesMap.keySet()
                        ));

                stuTotalCount.set(students.size());
            }

            return classesMap;
        });


        //获取请求延期中的人
        List<WorkPutPostponeRecord> workPutPostponeRecords = workPutPostponeRecordMapper.selectList(
                new LambdaQueryWrapper<WorkPutPostponeRecord>()
                        .eq(WorkPutPostponeRecord::getWpId, wpId)
        );

        int putPostponeStuCount = workPutPostponeRecords.size();

        List<Integer> stuIds = workPutPostponeRecords.stream()
                .map(WorkPutPostponeRecord::getStuId).collect(Collectors.toList());
        if(stuIds.size() == 0) return R.error().add("error", "暂无学生数据");
        List<Students> stuInfo = studentsMapper.selectBatchIds(stuIds);

        try {
            Map<Integer, Classes> classesMap = getClassesInfoTask.get();
            if (stuTotalCount.get() == 0) return R.error().add("error", "暂无学生数据");
            stuInfo.forEach(s -> {
                s.setClassName(classesMap.get(s.getBelongClassId()).getClassRealName());
            });
            double putPostponeRating = putPostponeStuCount *1.0 / stuTotalCount.get();

            return R.success().add("putPostponeRating", putPostponeRating)
                    .add("stus", stuInfo)
                    .add("work", work);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            return R.error();
        }

    }

    @Override
    @Transactional
    public R decideThePostpone(Integer wpId, JSONObject json) {
        Boolean isAgree = json.getBoolean("isAgree");
        WorkPostpone postpone = getById(wpId);
        if (postpone == null) return R.error();

        if (isAgree) {
            LocalDateTime time = json.getObject("time", LocalDateTime.class);

            this.updateById(
                    new WorkPostpone().setWpId(wpId).setIsReply(1).setPostponeTime(time).setDeleted(1)
            );
            LocalDateTime now = LocalDateTime.now();
            if (time.isAfter(now)) {
                workMapper.updateById(new Work().setWorkId(postpone.getWorkId()).setEndTime(time).setEnd(0));
                this.removeById(postpone);
            }else {
                return R.error();
            }

            workPutPostponeRecordMapper.update(null,
                    new LambdaUpdateWrapper<WorkPutPostponeRecord>()
                            .set(WorkPutPostponeRecord::getStatus, 1)
                            .eq(WorkPutPostponeRecord::getWpId, wpId)
            );

        }else {
            //1为同意，2为拒绝
            this.updateById(
                    new WorkPostpone().setWpId(wpId).setIsReply(2).setDeleted(1)
            );
            this.removeById(postpone);
            workPutPostponeRecordMapper.update(null,
                    new LambdaUpdateWrapper<WorkPutPostponeRecord>()
                            .set(WorkPutPostponeRecord::getStatus, 2)
                            .eq(WorkPutPostponeRecord::getWpId, wpId)
            );
        }

        return R.success();
    }

    public List<WorkPostpone> listIgnoreDeleteBatchIds(Collection ids) {
        return workPostponeMapper.listIgnoreDeleteBatchIds(ids);
    }
}
